---
title: DDL
description: 使用DDL创建数据库&数据表
---
DDL是 DBMS 的核心组件，也是 SQL 的重要组成部分吗，DDL 的正确性和稳定是是 SQL 运行的重要基础。

1. 如何定义数据库和数据表
2. DDL定义数据表时，都有那些约束性；
3. 使用DDL 设计数据库时，都有那些重要的原则；

## DDL的基础语法
DDL 的英文全称是 Data Definition Language,中文是数据定义语言。它定义了数据库的结构和数据表的结构。

在 DDL 中，常用的功能是增删改，分别对应的命令是 CREATE、 DROP、 ALTER。在执行 DDL 的时候，不需要 COMMIT 就可以完成任务。

### 对数据库进行定义
```sql
CREATE DATABASE test_db; // 创建一个名为test_db的数据库
DROP DATABASE test_db;//删除一个名为test_db 的数据库
```
### 对数据表进行定义
创建表结构的语法如下：
```sql
CREATE TABLE [table_name](字段名 数据类型,......)
```
## 创建表结构
比如我们想创建一个球员表，表名为 player，其中 player_id 是数据表的 player 的主键，且自动增长。其余三个字段均不能为空。然后对 player_name 字段进行索引，索引类型为 unique。


<img src="https://img.wkq.pub/hexo/4925e0c2a1342f4b19d29f0d665afbdd.webp"/>

```sql
DROP TABLE IF EXISTS `player`;
CREATE TABLE `player`(
	`player_id` int(11) NOT NULL AUTO_INCREMENT,
    `team_id` int(11) NOT NULL,
    `player_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
    `height` float(3,2) NOT NULL,
    PRIMARY KEY (`player_id`) USING BTREE,
    UNIQUE INDEX `palyer_name`(`player_name`) USING BTREE
)ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT=  Dynamic;
```

首先删除 player 表（如果数据库中存在该表的话）然后再创建 player 表，里面的数据表和字段都使用了反引号，这是为了避免它们的名称与 MySQL 保留字段相同，对数据表和字段名称都加上了反引号。

其中 player_name 字段的字符索引编码是 `utf8mb4`，排序规则是 `utf8mb4_general_ci`,代表队大小写不敏感。

因为 player_id 设置了主键，因此在 DDL 中使用 PRIMARY KEY 进行规定，同时索引方法采用 BTREE。

因为对 player_name 字段进行了索引，在设置字段索引时，我们可以设置为 UNIQUE INDEX（唯一索引），也可以设置为其它索引 NORMAL INDEX（普通索引）。

唯一索引和普通索引的区别在于它对字段进行了唯一性的约束。在索引方式上，可以选择 BTREE 或者 HASH，这里采用 BTREE 的方法进行索引。

整个数据表的存储规则采用 InnoDB。

## 修改表结构

在创建表结构之后，还可以对表结构进行修改。

1. 添加字段，在数据表中添加一个 age字段，类型为 int(11)

   ```sql
   mysql> ALTER TABLE `player` ADD (age int(11),sex int);
   Query OK, 0 rows affected, 1 warning (0.01 sec)
   Records: 0  Duplicates: 0  Warnings: 1
   ```

2. 修改字段名，将 age 字段改为 player_age

   ```sql
   mysql> alter table player rename column age to player_age;
   Query OK, 0 rows affected (0.01 sec)
   Records: 0  Duplicates: 0  Warnings: 0
   ```

3. 修改字段的数据类型，将 player_age 的数据类型设置为 float(3,1)

   ```sql
   mysql> ALTER TABLE player MODIFY COLUMN player_age float(3,1);
   Query OK, 0 rows affected, 1 warning (0.03 sec)
   Records: 0  Duplicates: 0  Warnings: 1
   ```

4. 删除字段，删除刚刚添加的 player_age 字段。

   ```sql
   ALTER TABLE player DROP COLUMN player_age;
   ```



## 数据表的常见约束

当我们创建表的时候，还会对字段进行约束，约束的目的在于保证 RDBMS 里面的数据的准确性和一致性。

首先是主键约束。

主键起的作用是唯一标识一条记录，不能重复、不能为空，即 UNIQUE+NOT NULL。一个数据表的主键只能有一个。主键可以是一个字段，也可以由多个字段复合组成。

其次是外键约束。

外键确保了表与表之间引用的完整性。一个表中的外键对应另一张表的主键。外键可以是重复的，也可以为空。比如 player_id 在 player 表中是主键，如果你想设置一个球员比分表即 player_score ,就可以在 player_score 中设置 player_id 为外键，关联到 player 表中。

除了对键进行约束外，还有字段约束。

唯一性约束。

唯一性约束表明了字段在表中的数值是唯一的，即使我们已经有了主键，还可以对其它字段进行唯一性约束。比如 在 player 表中对 player_name 设置唯一性约束，就表明任何两个球员的姓名不能相同。唯一性约束和普通索引（NORMAL INDEX）之间是有区别的。唯一性约束相当于创建了一个约束和一个普通索引，目的是保证字段的正确性，而普通索引只是提升数据检索的速度，并不对字段的唯一性进行约束。

NOT NULL 约束，对字段定义了 NOT NULL，则表明该字段不应为空，必须有取值。

DEFAUTL 约束，表明了字段的默认值。如果在插入数据的时候，这个字段没有值，就设置为默认值。

CHECK 约束，用来检查特定字段取值范围的有效性，CHECK 约束的结果不能为 FALSE。比如可以对身高 height 的数值进行 CHECK 约束，必须 >=0 ，且 <3 ，即

CHECK(height >=0 AND height <3)。

## 设计数据表的原则

#### 数据表的个数越少越好

RDBMS 的核心在于对实体和联系的定义，也就是 E-R图（Entity Relationship Diagram），数据表越少，证明实体和联系设计的越简洁。

#### 数据表中的字段个数越少越好

字段个数越多，数据冗余的可能性越大。设置字段个数少的前提是各个字段相互独立，而不是某个字段的取值可以由其它字段计算出来。通常会在数据冗余和检索效率中进行平衡。

#### 数据表中联合主键的字段个数越少越好

设置主键是为了确定唯一性，当一个字段无法确定唯一性的时候，就需要采用联合主键的方式（也就是多个字段来定义一个主键）。联合主键中的字段越多，占用的索引空间就越大，不仅增大理解难度，还会增加运行时间和索引空间，因此联合主键的字段个数越少越好。

#### 使用主键和外键越多越好

数据库的设计实际上就是定义各种表，以及各种字段之间的关系，这些关系越多，证明这些实体之间的冗余度越低，利用率越高。

:::tip

更少的表、更少的字段、更少的联合主键字段，提高主键、外键的利用率。

:::



